﻿using BarrierGenarator.Data;
using Snake.Data;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace BarrierGenarator
{
    public partial class Frm_Editor : Form
    {

        enum CompomentType
        {
            None,
            Gate,
            Wall,
            Trap,
            SnakeHead,
            //Potion
        }

        enum PainMethod
        {
            Free,
            Dash,
            Vertical,
            //Rectangel
        }


        //各种flag
        bool arrivalflag = false;
        bool paintflag = false;
        bool mousecontinuepaintflag = false;

        //连续绘制所需两个点
        LocationD beginp = new LocationD();
        LocationD endp = new LocationD();

        CompomentType compomenttype = CompomentType.None;
        PainMethod pm = PainMethod.Free;

        const int LEFTBOARD = 250;

        public Frm_Editor()
        {
            InitializeComponent();
            rdb_up.Checked = true;
            rdb_free.Checked = true;
            rdb_wall.Checked = true;
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.Clear(Color.White);
            g.FillRectangle(Brushes.Red, new Rectangle(General.SnakeHead.X * 15 + LEFTBOARD, General.SnakeHead.Y * 15, 15, 15));
            for(int i=1;i<=General.SnakeSize;i++)
            {
                g.FillRectangle(Brushes.Blue, new Rectangle((General.SnakeHead.X - i) * 15 + LEFTBOARD, General.SnakeHead.Y * 15, 15, 15));
            }

            foreach(var wall in General.Walls)
            {
                g.FillRectangle(Brushes.Black, new Rectangle(wall.X * 15+LEFTBOARD, wall.Y * 15, 15, 15));
            }
            foreach (var gate in General.Gates.Gates)
            {
                g.FillRectangle(Brushes.SkyBlue, new Rectangle(gate.Location.X * 15+LEFTBOARD, gate.Location.Y * 15, 15, 15));
            }
            foreach (var trap in General.Traps)
            {
                g.FillRectangle(Brushes.Brown, new Rectangle(trap.X * 15 + LEFTBOARD, trap.Y * 15, 15, 15));
            }

            for (int i = 0; i <= General.Size.Width; i++)
            {
                g.DrawLine(Pens.Red, i * 15 + LEFTBOARD, 0, i * 15 + LEFTBOARD, General.Size.Height * 15);
                if (i < General.Size.Width)
                    g.DrawString(i.ToString(), new Font("黑体", 8, FontStyle.Bold), Brushes.Red, i * 15 + LEFTBOARD, General.Size.Height * 15);
            }
            for (int i = 0; i <= General.Size.Height; i++)
            {
                g.DrawLine(Pens.Red, LEFTBOARD, i * 15, General.Size.Width * 15 + LEFTBOARD, i * 15);
                if (i < General.Size.Height)
                    g.DrawString(i.ToString(), new Font("黑体", 8, FontStyle.Bold), Brushes.Red, General.Size.Width * 15 + LEFTBOARD, i * 15);
            }
        }


        private void Frm_Editor_MouseClick(object sender, MouseEventArgs e)
        {
            if (!arrivalflag)
            {
                switch(pm)
                {
                    case PainMethod.Free:
                        if (e.X < General.Size.Width * 15 + LEFTBOARD && e.Y < General.Size.Height * 15
                        && e.X > LEFTBOARD)
                        {
                            LocationD location = new LocationD((e.X - LEFTBOARD) / 15, e.Y / 15);
                            if (General.CheckWallExist(location))
                            {
                                General.Walls.Remove(General.GetWall(location));
                            }
                            else if (General.CheckGateExist(location))
                            {
                                General.Gates.Gates.Remove(General.GetGate(location));
                                arrivalflag = false;
                            }
                            else if (General.CheckTrapExist(location))
                            {
                                General.Traps.Remove(General.GetTrap(location));
                            }
                            else
                            {
                                switch (compomenttype)
                                {
                                    case CompomentType.Wall:
                                        General.Walls.Add(location);
                                        break;
                                    case CompomentType.Gate:
                                        var direction = Snake.Snake.SnakeDirection.None;

                                        if (rdb_up.Checked)
                                        {
                                            direction = Snake.Snake.SnakeDirection.Up;
                                        }
                                        else if (rdb_down.Checked)
                                        {
                                            direction = Snake.Snake.SnakeDirection.Down;
                                        }
                                        else if (rdb_left.Checked)
                                        {
                                            direction = Snake.Snake.SnakeDirection.Left;
                                        }
                                        else if (rdb_right.Checked)
                                        {
                                            direction = Snake.Snake.SnakeDirection.Right;
                                        }

                                        if ((e.X - LEFTBOARD) < General.Size.Width * 15 && e.Y < General.Size.Height * 15 && e.X > LEFTBOARD)
                                        {
                                            if (General.CheckGateExist(location))
                                            {
                                                General.Gates.Gates.Remove(General.GetGate(location));
                                                arrivalflag = false;
                                            }
                                            else
                                            {
                                                arrivalflag = true;
                                                General.Gates.Gates.Add(new GateD()
                                                {
                                                    Location = location,
                                                    Arrival = new LocationD(20, 20),
                                                    Direction = direction
                                                });
                                            }
                                        }
                                        break;
                                    case CompomentType.Trap:
                                        General.Traps.Add(location);
                                        break;
                                    case CompomentType.SnakeHead:
                                        General.SnakeHead = location;
                                        break;
                                }
                            }
                        }
                        break;
                    case PainMethod.Dash:
                        if (!paintflag)
                        {
                            beginp = new LocationD((e.X - LEFTBOARD) / 15, e.Y / 15);
                            paintflag = true;
                        }
                        else
                        {
                            endp = new LocationD((e.X - LEFTBOARD) / 15, beginp.Y);
                            if (endp.X == beginp.X)
                                break;
                            else if(endp.X>beginp.X)
                            {
                                for(int i=beginp.X;i<=endp.X;i++)
                                {
                                    var locationd = new LocationD(i, beginp.Y);

                                    if (compomenttype == CompomentType.Trap)
                                    {
                                        if (General.CheckTrapExist(locationd))
                                            continue;
                                        else if(General.CheckWallExist(locationd))                                        
                                            General.Walls.Remove(General.GetWall(locationd));                                        
                                        else if(General.CheckGateExist(locationd))
                                            continue;

                                        General.Traps.Add(locationd);
                                    }
                                    else if (compomenttype == CompomentType.Wall)
                                    {
                                        if (General.CheckTrapExist(locationd))
                                            General.Traps.Remove(General.GetTrap(locationd));
                                        else if (General.CheckWallExist(locationd))
                                            continue;
                                        else if (General.CheckGateExist(locationd))
                                            continue;
                                        
                                        General.Walls.Add(locationd);
                                    }
                                }
                            }
                            else
                            {
                                for (int i = beginp.X; i >= endp.X; i--)
                                {
                                    var locationd = new LocationD(i, beginp.Y);

                                    if (compomenttype == CompomentType.Trap)
                                    {
                                        if (General.CheckTrapExist(locationd))
                                            continue;
                                        else if (General.CheckWallExist(locationd))
                                            General.Walls.Remove(General.GetWall(locationd));
                                        else if (General.CheckGateExist(locationd))
                                            continue;

                                        General.Traps.Add(locationd);
                                    }
                                    else if (compomenttype == CompomentType.Wall)
                                    {

                                        if (General.CheckTrapExist(locationd))
                                            General.Traps.Remove(General.GetTrap(locationd));
                                        else if (General.CheckWallExist(locationd))
                                            continue;
                                        else if (General.CheckGateExist(locationd))
                                            continue;

                                        General.Walls.Add(locationd);
                                    }
                                }
                            }
                            paintflag = false;
                        }
                        break;
                    case PainMethod.Vertical:
                        if (!paintflag)
                        {
                            beginp = new LocationD((e.X - LEFTBOARD) / 15, e.Y / 15);
                            paintflag = true;
                        }
                        else
                        {
                            endp = new LocationD(beginp.X, e.Y/15);
                            if (endp.Y == beginp.Y)
                                break;
                            else if (endp.Y > beginp.Y)
                            {
                                for (int i = beginp.Y; i <= endp.Y; i++)
                                {
                                    var locationd = new LocationD(beginp.X, i);
                                    if (compomenttype == CompomentType.Trap)
                                    {
                                        if (General.CheckTrapExist(locationd))
                                            continue;
                                        else if (General.CheckWallExist(locationd))
                                            General.Walls.Remove(locationd);
                                        else if (General.CheckGateExist(locationd))
                                            continue;

                                        General.Traps.Add(locationd);
                                    }

                                    else if (compomenttype == CompomentType.Wall)
                                    {
                                        if (General.CheckTrapExist(locationd))
                                            General.Traps.Remove(locationd);
                                        else if (General.CheckWallExist(locationd))
                                            continue;
                                        else if (General.CheckGateExist(locationd))
                                            continue;

                                        General.Walls.Add(locationd);
                                    }
                                }
                            }
                            else
                            {
                                for (int i = beginp.Y; i >= endp.Y; i--)
                                {
                                    var locationd = new LocationD(beginp.X, i);
                                    if (compomenttype == CompomentType.Trap)
                                    {
                                        if (General.CheckTrapExist(locationd))
                                            continue;
                                        else if (General.CheckWallExist(locationd))
                                            General.Walls.Remove(locationd);
                                        else if (General.CheckGateExist(locationd))
                                            continue;

                                        General.Traps.Add(locationd);
                                    }

                                    else if (compomenttype == CompomentType.Wall)
                                    {
                                        if (General.CheckTrapExist(locationd))
                                            General.Traps.Remove(locationd);
                                        else if (General.CheckWallExist(locationd))
                                            continue;
                                        else if (General.CheckGateExist(locationd))
                                            continue;

                                        General.Walls.Add(locationd);
                                    }
                                }
                            }
                            paintflag = false;
                        }
                        break;
                }
                Invalidate(false);
            }
            else
            {
                if ((e.X - LEFTBOARD) < General.Size.Width * 15 && e.Y < General.Size.Height * 15 && e.X > LEFTBOARD)
                {
                    var location = new LocationD((e.X - LEFTBOARD) / 15, e.Y / 15);
                    if (General.CheckGateExist(location))
                    {
                        General.Gates.Gates.Remove(General.GetGate(location));
                        arrivalflag = false;
                    }
                    else
                    {
                        General.Gates.Gates.Last().Arrival = new LocationD(location.X, location.Y);
                        var direction = Snake.Snake.SnakeDirection.None;
                        if (rdb_up.Checked)
                        {
                            direction = Snake.Snake.SnakeDirection.Up;
                        }
                        else if (rdb_down.Checked)
                        {
                            direction = Snake.Snake.SnakeDirection.Down;
                        }
                        else if (rdb_left.Checked)
                        {
                            direction = Snake.Snake.SnakeDirection.Left;
                        }
                        else if (rdb_right.Checked)
                        {
                            direction = Snake.Snake.SnakeDirection.Right;
                        }

                        General.Gates.Gates.Last().Direction = direction;
                        arrivalflag = false;
                        Invalidate(false);
                    }
                }
            }
        }

        private void Frm_Editor_MouseDown(object sender, MouseEventArgs e)
        {
            if (!arrivalflag)
            {
                //之后可以将检测 radiobutton 封装到函数里
                if (rdb_vertical.Checked)
                {
                    pm = PainMethod.Vertical;
                }
                else if (rdb_dash.Checked)
                {
                    pm = PainMethod.Dash;
                }
                else if (rdb_free.Checked)
                {
                    pm = PainMethod.Free;
                }

                if (rdb_gate.Checked)
                {
                    compomenttype = CompomentType.Gate;
                }
                else if (rdb_trap.Checked)
                {
                    compomenttype = CompomentType.Trap;
                }
                else if (rdb_wall.Checked)
                {
                    compomenttype = CompomentType.Wall;
                }
                else if(rdb_snake.Checked)
                {
                    compomenttype = CompomentType.SnakeHead;
                }
                switch (compomenttype)
                {
                    case CompomentType.Wall:
                        mousecontinuepaintflag = true;
                        break;
                    case CompomentType.Trap:
                        mousecontinuepaintflag = true;
                        break;
                }
            }
            
        }

        private void Frm_Editor_MouseMove(object sender, MouseEventArgs e)
        {
            
            if ((e.X-LEFTBOARD) < General.Size.Width * 15 
                && e.Y < General.Size.Height * 15
                &&e.X>LEFTBOARD)
            {
                LocationD location = new LocationD((e.X-LEFTBOARD) / 15, e.Y / 15);
                Text = location.ToString();
                if (!mousecontinuepaintflag) return;
                
                switch(compomenttype)
                {
                    case CompomentType.Wall:
                        if (!General.CheckWallExist(location))
                        {
                            General.Walls.Add(location);
                        }
                        break;
                    case CompomentType.Trap:
                        if (!General.CheckTrapExist(location))
                        {
                            General.Traps.Add(location);
                        }
                        break;
                }
                
            }

        }

        private void Frm_Editor_MouseUp(object sender, MouseEventArgs e)
        {
            mousecontinuepaintflag = false;
            Invalidate();
        }


        private void btn_clearallwall_Click(object sender, EventArgs e)
        {
            General.Walls.Clear();
            Invalidate(false);
        }

        private void btn_revoke_Click(object sender, EventArgs e)
        {

        }

        private void btn_clearallgate_Click(object sender, EventArgs e)
        {
            General.Gates.Gates.Clear();
            Invalidate(false);
        }

        private void btn_clearalltrap_Click(object sender, EventArgs e)
        {
            General.Traps.Clear();
            Invalidate(false);
        }

        private void btn_clearall_Click(object sender, EventArgs e)
        {
            General.Walls.Clear();
            General.Gates.Gates.Clear();
            General.Traps.Clear();
            Invalidate(false);
        }

        
    }
}
